﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace rFDevLib {

    public class TorqueCurveGraphic {
        // Parameters for external use
        public int xRes = 740, yRes = 300; // Bitmap resolution
        public double margin = 10.0; // Margin around outside to remain blank, like a border

        // Members for internal use
        private double top = 0.0;
        private double iHeight = 0.0;
        private double left = 0.0;
        private double iWidth;
        private double vertZero = 0.0;

        private double maxTorque;

        private Bitmap bmp;
        private Graphics gfx;

        public void NewGraphic( double MinTorque, double MaxTorque, double MaxRPM ) {
            bmp = new Bitmap( xRes, yRes );
            gfx = Graphics.FromImage( bmp );
            gfx.Clear( Color.White );
            gfx.SmoothingMode = SmoothingMode.HighQuality;

            maxTorque = MaxTorque;

            top = (double)yRes;
            iHeight = -(double)yRes / (MaxTorque - (MinTorque*0.5));
            vertZero = -(MaxTorque * iHeight);
            iWidth = ((double)xRes - margin - margin) / MaxRPM;

            // Draw lines
            Pen b = new Pen( Color.Black, 1.5f );
            Pen g = new Pen( Color.Gray, 1.5f );
            Pen lg = new Pen( Color.LightGray, 1.5f );

            double rpmInt = 2000.0;
            double torqueInt = 100.0;

            gfx.DrawLine( b, ToBMPCoord( 0.0, MaxTorque ), ToBMPCoord( 0.0, MinTorque ) );
            for ( double i = rpmInt; i < MaxRPM; i += rpmInt )
                gfx.DrawLine( lg, ToBMPCoord( i, MaxTorque ), ToBMPCoord( i, MinTorque ) );

            gfx.DrawLine( b, ToBMPCoord( 0.0, 0.0 ), ToBMPCoord( MaxRPM, 0.0 ) );

            for ( double i = torqueInt; i < maxTorque; i += torqueInt )
                gfx.DrawLine( g, ToBMPCoord( 0.0, i ), ToBMPCoord( MaxRPM, i ) );
        }

        private Point ToBMPCoord( double x, double y ) {
            return new Point( (int)(left + (x * iWidth)), (int)(vertZero + (y * iHeight)) );
        }

        public void DrawTorqueCurve( List<double> rpm, List<double> torque, Color c ) {
            Pen w = new Pen( Color.White, 2.0f );
            Pen b = new Pen( c, 1.5f );
            for ( int i = 0; i < Math.Max( rpm.Count, torque.Count )-1; i++ ) {
                Point s = ToBMPCoord( rpm[i], torque[i] ),
                    e = ToBMPCoord( rpm[i + 1], torque[i + 1] );
                gfx.DrawLine( w, s, e );
                gfx.DrawLine( b, s, e );
            }
        }

        public void AddRPMLimit( double rpm ) {
            Pen b = new Pen( Color.OrangeRed, 1.5f );

            gfx.DrawLine( b, ToBMPCoord( rpm, maxTorque ), ToBMPCoord( rpm, 0.0 ) );

            return;
        }

        public Bitmap GetBmp() {
            return bmp;
        }

        public System.Windows.Media.Imaging.BitmapSource GetBmpSrc() {
            return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                  bmp.GetHbitmap(),
                  IntPtr.Zero,
                  System.Windows.Int32Rect.Empty,
                  System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions() );
        }
    }
}
